<?php

defined('IN_MY_PHP') || die(0);

// 初始化本文件单独使用时涉及到的常量
defined('CRLF') || define('CRLF', "\r\n");
defined('DS') || define('DS', DIRECTORY_SEPARATOR);
defined('ERROR_FILE') || define('ERROR_FILE',rtrim(preg_replace('/\\\\\\//', DS, $_SERVER['DOCUMENT_ROOT']), DS) . DS . '#!dev' . DS . 'error.log');
defined('ERROR_ARC_FILE') || define('ERROR_ARC_FILE',rtrim(preg_replace('/\\\\\\//', DS, $_SERVER['DOCUMENT_ROOT']), DS) . DS . '#!dev' . DS . 'error_arc.log');
/**
 * 异常捕获及错误处理类.
 * ERROR TYPE: RUNTIME , SYNTAX AND LOGIC.
 *
 * @author netmou <leiyanfo@sina.com>
 */
class Guard extends Exception
{
	private static $errorLevel = null;

	public static function errorGuard($errno, $msg, $file, $line)
	{
		switch ($errno) {
			case E_ERROR:
			case E_USER_ERROR:
				self::$errorLevel = 'Fatal Error';
				break;
			case E_WARNING:
			case E_USER_WARNING:
				self::$errorLevel = 'Warning Error';
				break;
			case E_NOTICE:
			case E_USER_NOTICE:
				self::$errorLevel = 'Notice Error';
				break;
			default:
				self::$errorLevel = 'Unknown Error';
		}
		throw new ErrorException($msg, 0, $errno, $file, $line);
	}
	public static function friendlyMessage($code)
	{
		$desc = '^_^程序出错了，错误级别代码：'.$code.'<br />';
		$desc .= '为了安全，已屏蔽具体错误原因，但可能是以下原因，请先自我检查：<br />';
		$desc .= '(1)输入的不是程序预期的值<br />';
		$desc .= '---如，不能识别的数字(通常面积、金钱、数量等数值不用带单位，不能使用佰、仟、万、亿等汉字)；<br />';
		$desc .= '---如，不能识别的的日期等格式(正确格式：日期如2012-12-12;时间如2012-12-12 12:12:12)；<br />';
		$desc .= '---如，导入或输入的的个别数据超出预设长度（像电话、邮箱等输入了两个值等就会超出预设长度）；<br />';
		$desc .= '---如，导入的文件太大，可以尝试将文件（xls）分成几个文件导入（前几行的列头要预留，不能省略）<br />';
		$desc .= '---如，导入的数据的格式、列的顺序不符合模版要求，请按模板列顺序、格式要求整理后重试；<br />';
		$desc .= '---如，浏览器太古老，建议使用Chome、Firefox等浏览器的最新版；<br />';
		$desc .= '(2)程序可能存在小问题，请联系技术支持！<br />';
		$desc .= date('r') . '<br />';
		if ($_SERVER['HTTP_REFERER'] != null) {
			$desc .= '<a style="cursor:pointer;font-size:12px;" href="javascript:history.go(-1)">点击返回</a>';
		}
		echo $desc;
		exit(0);
	}
	public static function formatTrace($e)
	{
		$traceLog = null;
		$traces = $e->getTrace();
		$xh = 0;
		foreach ($traces as $k => &$trace) {
			if (empty($trace['file'])) {
				try {
					if (isset($trace['class'])) {
						$reflection = new ReflectionMethod($trace['class'], $trace['function']);
					} else {
						$reflection = new ReflectionFunction($trace['function']);
					}
					$trace['file'] = $reflection->getFileName();
					$trace['line'] = $reflection->getStartLine();
				} catch (Exception $e) {
					continue;
				}
			}
			$traceLog .= '--- #> '.(++$xh).' ';
			if (isset($trace['class'])) {
				$traceLog .= $trace['class'].$trace['type'].$trace['function'];
			} else {
				$traceLog .= $trace['function'];
			}
			$traceLog .= '(..) On line '.$trace['line'].' In file "'.$trace['file'].'"'.CRLF;
		}

		return $traceLog;
	}

	public static function exceptDesc($e)
	{
		if (!headers_sent()) {
			header('Content-type: text/html; charset=utf-8');
		}
		$desc = 'Oops..., your program encounters a problem!'.CRLF;
		$desc = $desc.'#> ExceptionType: '.get_class($e).CRLF;
		$desc = $desc.'#> ErrorLevel: '.self::$errorLevel.CRLF;
		$desc = $desc.'#> ErrorMessage: '.$e->getMessage().CRLF;
		$desc = $desc.'#> ErrorFile: '.str_replace(PROJECT_PATH, '', $e->getFile()).CRLF;
		$desc = $desc.'#> ErrorLine: '.$e->getLine().CRLF;
		$desc = $desc.'#> ErrorTrace:'.CRLF.self::formatTrace($e).CRLF;

		$detail = str_repeat("=", 120).CRLF;
		$detail = $detail.'Unix-Timestamp: '.date('Y-m-d H:i:s').CRLF;
		$detail = $detail.'HTTP_REFERER: '.$_SERVER['HTTP_REFERER'].CRLF;
		$detail = $detail.'HTTP_REQUEST_URI: '.$_SERVER['REQUEST_URI'].CRLF;
		$detail = $detail.'HTTP_VAR $_POST: '.var_export($_POST, true).CRLF;
		$detail = $detail.'HTTP_VAR $_FILES: '.var_export($_FILES, true).CRLF;
		$detail = $detail.'HTTP_VAR $_SESSION: '.var_export($_SESSION, true).CRLF;
		$detail = $detail.'HTTP_VAR $_COOKIE: '.var_export($_COOKIE, true).CRLF;
		$detail = $detail.$desc;
		$error_dir = dirname(ERROR_FILE);
		if (!file_exists($error_dir)) {
			mkdir($error_dir, 0644, true);
		}
		//限制日志文件大小256KB,每次超出后进行归档(保证总是能查看最近256KB的日志)
		if (file_exists(ERROR_FILE) && filesize(ERROR_FILE) >= 256000) {
			if(file_exists(ERROR_ARC_FILE)){
				unlink(ERROR_ARC_FILE);
			}
			copy(ERROR_FILE, ERROR_ARC_FILE);
			unlink(ERROR_FILE);
		}
		file_put_contents(ERROR_FILE, $detail, FILE_APPEND | LOCK_EX);
		if (Master::singleton()->isLocalRequest() === false) {
			//输出安全的异常提示信息，并结束程序。
			self::friendlyMessage(self::$errorLevel);
		}
		echo nl2br(htmlentities($desc, ENT_QUOTES, 'UTF-8'));
		echo "<a class='tip-danger pointer' href='javascript:window.history.go(-1)'>点击我返回</a>";
		exit(0); //结束程序
	}
}

set_exception_handler('Guard::exceptDesc');
set_error_handler('Guard::errorGuard', E_ALL & ~ E_DEPRECATED & ~ E_NOTICE);